//用冒泡函数的方式模拟qsort函数的工作原理。
//其实qsort的底层逻辑是快速排序。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

void swap_mn(void* p1, void* p2, int width)
{
	int i = 0;
	for (i = 0; i < width; i++)
	{
        //因为不知道数组和元素的类型，所以都强制转换为char*类型，之后一个字节一个字节的交换来实现这两个数字的交换。
		char tmp = *((char*)p2 + i);
		*((char*)p2 + i) = *((char*)p1 + i);  //注意最外面的括号不要把*解引用操作符放进去，解引用操作符是对整个的表达式进行操作的。
		*((char*)p1 + i) = tmp;
	}
}

int int_cmp(const void* p1, const void* p2)
{
	return (*(const int*)p1 - *(const int*)p2);
}

void bubble_sort_mn(void* base, int sz, int width, int(*cmp)(void*, void*)) //最后面的传参，是传的函数指针。
{
	int i = 0;
	int j = 0;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;  //默认flag = 1；如果交换了flag就变了，如果没交换，就代表这一排数据已经排序完毕，就不需要在进行反复的循环，与后面的判断相照应，就可以跳出循环。
		for (j = 0; j < sz - 1 - i; j++)
		{ 
            //因为不知道数组的类型，所以把base强制转化为char*类型，之后访问数组后面元素时，就可以用j*在mian函数中传过来的width来实现指针的跳跃。
			if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0)    //qsort默认是升序的原因是前一个元素-后一个元素为整数，则需要交换。
			{                                                                       //当把自己写的函数中p1和p2的位置调换则变为降序，或者把此处的>换成<。
				flag = 0;
				swap_mn((char*)base + j * width, (char*)base + (j + 1) * width, width); //交换函数
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
}

int main()
{
	int arr[10] = { 1,4,3,2,6,9,5,8,0,7 };
	int sz = sizeof(arr) / sizeof(int);
	int i = 0;
	bubble_sort_mn(arr, sz, sizeof(int), int_cmp);
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}